home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <sys/types.h>
- #include <dos.h>
- #include <pc.h>
- #include <go32.h>
- #include <dpmi.h>
- #define far
- #include "ed.h"
- #include "paging.h"
- #include "perform.h"
- #include "fsfuncts.h"
-
- #define timer_channel 0x40 /* Timer channel (#0) of the timer chip */
- #define command_reg 0x43 /* Command register of the timer chip */
- #define ch_0_seq 0x36 /* 00110110 : ch 0, 2 bytes, mode 3, bin */
- #define pulses_per_mili 1193 /* Number of pulses per call to New08() */
- #define calls_per_tick 55 /* 65536/pulses_per_mili=calls per .055s */
- #define dos_clock_limit 0x0000fffe /* 65535 */
-
- extern Go32_Info_Block _go32_info_block;
-
- typedef struct {
- unsigned short limit;
- unsigned short base_lo;
- unsigned long base_hi;
- } IDT_STRUCT;
-
- typedef struct {
- unsigned short offset_lo;
- unsigned short selector;
- unsigned short type;
- unsigned short offset_hi;
- } IDT_ENTRY;
-
- typedef struct {
- unsigned short segment_limit;
- unsigned short base_00_15;
- unsigned char base_16_23;
- unsigned char dummy1;
- unsigned char dummy2;
- unsigned char base_24_31;
- } GDT_ENTRY;
-
- IDT_STRUCT idt, gdt;
-
- EVAL_DATA_TABLE evaluation_data;
- word32 total_hits_count = 0;
- int total_segments = EVAL_SEGMENTS;
- int timer_is_set = 0;
- int evaluation_is_running = 0;
-
- static _go32_dpmi_seginfo old_rm_isr;
- static _go32_dpmi_registers old_isr_regs;
- static _go32_dpmi_seginfo emu_rm_si;
- static _go32_dpmi_registers emu_rm_regs;
- static _go32_dpmi_seginfo emu_pm_si;
- static _go32_dpmi_seginfo pm_si;
- static IDT_ENTRY pm_old_idt_entry;
- static union REGS regs;
-
- volatile word32 dos_clock_tick = 0;
- volatile word32 ebp, eip, esp;
- static word32 segment_str_addr = 0, segment_stp_addr = 0, segment_len = 1;
-
- static int ok_to_run = 0;
-
- /* ---------------------------------------------------------------------- */
- static void
- get_idt_entry (int vectnum, IDT_ENTRY *idt_entry)
- {
- unsigned long idt_base, gdt_base;
- int idt_index = vectnum & 0xff;
- IDT_ENTRY *i_e;
-
- asm("movl $_idt,%eax");
- asm("sidt (%eax)");
- asm("movl $_gdt,%eax");
- asm("sgdt (%eax)");
-
- if (idt_index >= 0x08 && idt_index <= 0x0f)
- idt_index += _go32_info_block.master_interrupt_controller_base - 8;
- else if (idt_index >= 0x70 && idt_index <= 0x77)
- idt_index += _go32_info_block.slave_interrupt_controller_base - 0x70;
-
- idt_base = (idt.base_hi << 16) + idt.base_lo + 0xe0000000;
- gdt_base = (gdt.base_hi << 16) + gdt.base_lo + 0xe0000000;
-
- i_e = (IDT_ENTRY *)(idt_base + 8 * idt_index);
-
- if (i_e->selector > gdt.limit)
- return;
-
- idt_entry->offset_lo = i_e->offset_lo;
- idt_entry->selector = i_e->selector;
- idt_entry->type = i_e->type;
- idt_entry->offset_hi = i_e->offset_hi;
- }
- /* ---------------------------------------------------------------------- */
- static void
- set_idt_entry (int vectnum, IDT_ENTRY *idt_entry)
- {
- unsigned long idt_base, gdt_base;
- int idt_index = vectnum & 0xff;
- IDT_ENTRY *i_e;
-
- asm("movl $_idt,%eax");
- asm("sidt (%eax)");
- asm("movl $_gdt,%eax");
- asm("sgdt (%eax)");
-
- if (idt_index >= 0x08 && idt_index <= 0x0f)
- idt_index += _go32_info_block.master_interrupt_controller_base - 8;
- else if (idt_index >= 0x70 && idt_index <= 0x77)
- idt_index += _go32_info_block.slave_interrupt_controller_base - 0x70;
-
- idt_base = (idt.base_hi << 16) + idt.base_lo + 0xe0000000;
- gdt_base = (gdt.base_hi << 16) + gdt.base_lo + 0xe0000000;
-
- i_e = (IDT_ENTRY *)(idt_base + 8 * idt_index);
-
- /* if (idt_entry->selector > gdt.limit)
- return;
- */ /* Has to comment out because the original selector might not be. */
-
- i_e->offset_lo = idt_entry->offset_lo;
- i_e->selector = idt_entry->selector;
- i_e->type = idt_entry->type;
- i_e->offset_hi = idt_entry->offset_hi;
- }
- /* ---------------------------------------------------------------------- */
- static void
- analyze_eip (void)
- { if (eip <= segment_stp_addr && eip >= segment_str_addr)
- {
- eip -= segment_str_addr;
- evaluation_data[eip / segment_len].hits_count++;
- }
- total_hits_count++;
- }
- /* ---------------------------------------------------------------------- */
- static void
- emulate_rm_isr_08 (void)
- {
- asm("cli");
- asm("push %eax");
- asm("push %edx");
- asm("push %ds");
- asm("push $0x48");
- asm("pop %ds");
- dos_clock_tick += pulses_per_mili;
- asm("mov $0x20,%al");
- asm("out %al,$0x20");
- asm("pop %ds");
- asm("pop %edx");
- asm("pop %eax");
- }
- /* ---------------------------------------------------------------------- */
- static void
- emulate_pm_isr_08 (void)
- {
- asm("cli");
- asm("push %eax");
- asm("push %ebx");
- asm("push %ecx");
- asm("push %edx");
- asm("push %ds");
- asm("push $0x48");
- asm("pop %ds");
-
- dos_clock_tick += pulses_per_mili;
- if (dos_clock_tick < dos_clock_limit)
- {
- asm("mov $0x20,%al");
- asm("out %al,$0x20");
- } else
- {
- asm("movl %ebp,_ebp");
- asm("movl %esp,_esp");
-
- old_isr_regs.x.cs = old_rm_isr.rm_segment;
- old_isr_regs.x.ip = old_rm_isr.rm_offset;
- old_isr_regs.x.ss = old_isr_regs.x.sp = 0;
- regs.x.ax = 0x302;
- regs.h.bh = 0;
- regs.x.cx = 0;
- regs.x.di = (unsigned long)(&old_isr_regs);
- int86 (0x31, ®s, ®s);
- asm("cli");
-
- asm("movl _esp,%esp");
- asm("movl _ebp,%ebp");
-
- dos_clock_tick -= dos_clock_limit;
- }
- asm("pop %ds");
- asm("pop %edx");
- asm("pop %ecx");
- asm("pop %ebx");
- asm("pop %eax");
- asm("leave");
- asm("iret");
- }
- /* ---------------------------------------------------------------------- */
- static void
- my_pm_isr_08 (void)
- {
- asm("push %eax");
- asm("push %ecx");
- asm("push %edx");
- asm("push %ds");
- asm("push $0x48");
- asm("pop %ds");
-
- if (ok_to_run)
- {
- asm("movl %ebp,%eax");
- asm("add $0x04,%eax");
- asm("movl (%eax),%edx");
- asm("movl %edx,_eip");
-
- analyze_eip ();
- }
-
- asm("pop %ds");
- asm("pop %edx");
- asm("pop %ecx");
- asm("pop %eax");
- asm("leave");
-
- asm("push %eax"); /* <=> db 50h */
- asm("push %eax"); /* <=> db 50h */
- asm("push %eax"); /* <=> db 50h */
- asm("push %eax"); /* <=> db 50h */
- asm("push %eax"); /* <=> db 50h */
- asm("push %eax"); /* <=> db 50h */
- asm("push %eax"); /* <=> db 50h */
- }
- /* ---------------------------------------------------------------------- */
- int
- set_timer ()
- {
- word32 old_selector, old_offset, jump_pos;
-
- if (_go32_info_block.run_mode == _GO32_RUN_MODE_DPMI)
- return (0);
- if (!timer_is_set)
- {
- pm_si.pm_offset = (int) my_pm_isr_08;
- pm_si.pm_selector = _go32_my_cs();
-
- asm("cli");
- get_idt_entry (8, &pm_old_idt_entry);
- asm("sti");
-
- jump_pos = (int) my_pm_isr_08 + 0x2b;
- old_offset = ((unsigned long)pm_old_idt_entry.offset_hi << 16) |
- (unsigned long)pm_old_idt_entry.offset_lo;
- old_selector = (unsigned long)pm_old_idt_entry.selector;
- if (old_offset)
- {
- write_child (jump_pos + 4, &old_selector, 2);
- write_child (jump_pos , &old_offset, 4);
- old_offset = 0xea; /* Opcode for intersegment jump */
- write_child (jump_pos - 1, &old_offset, 1);
-
- timer_is_set = 1;
- }
- else
- {
- int ret;
-
- emu_rm_si.pm_offset = (int) emulate_rm_isr_08;
- emu_pm_si.pm_offset = (int) emulate_pm_isr_08;
- emu_pm_si.pm_selector = _go32_my_cs();
-
- ret = _go32_dpmi_allocate_real_mode_callback_iret(
- &emu_rm_si, &emu_rm_regs);
- if (ret)
- return 0;
-
- disable();
-
- _go32_dpmi_get_real_mode_interrupt_vector(8, &old_rm_isr);
- _go32_dpmi_set_real_mode_interrupt_vector(8, &emu_rm_si);
- _go32_dpmi_set_protected_mode_interrupt_vector(8, &emu_pm_si);
-
- outportb (command_reg, ch_0_seq);
- outportb (timer_channel, pulses_per_mili & 0xff);
- outportb (timer_channel, pulses_per_mili >> 8);
-
- enable();
-
- old_offset = (unsigned long) emulate_pm_isr_08;
- old_selector = _go32_my_cs ();
- write_child (jump_pos + 4, &old_selector, 2);
- write_child (jump_pos , &old_offset, 4);
- old_offset = 0xea; /* Opcode for jump */
- write_child (jump_pos - 1, &old_offset, 1);
-
- timer_is_set = 2;
- }
-
- asm("cli");
- _go32_dpmi_set_protected_mode_interrupt_vector(8, &pm_si);
- asm("sti");
-
- return 1;
- }
- return 0;
- }
- /* ---------------------------------------------------------------------- */
- void
- reset_timer ()
- {
- if (timer_is_set)
- {
- asm("cli");
- set_idt_entry (8, &pm_old_idt_entry);
- asm("sti");
-
- if (timer_is_set == 2)
- {
- disable();
-
- outportb (command_reg, ch_0_seq);
- outportb (timer_channel, 0);
- outportb (timer_channel, 0);
-
- _go32_dpmi_set_real_mode_interrupt_vector(8, &old_rm_isr);
- _go32_dpmi_free_real_mode_callback (&emu_rm_si);
-
- enable();
- }
-
- timer_is_set = 0;
- }
- }
- /* ---------------------------------------------------------------------- */
- void
- start_evaluate ()
- {
- if (timer_is_set)
- {
- evaluation_is_running = 1;
- ok_to_run = 1;
- }
- }
- /* ---------------------------------------------------------------------- */
- void
- stop_evaluate ()
- {
- ok_to_run = 0;
- evaluation_is_running = 0;
- }
- /* ---------------------------------------------------------------------- */
- void
- init_eval_data (word32 start_addr, word32 stop_addr)
- {
- int i;
- word32 real_str = start_addr, real_stp = stop_addr;
-
- if ((!valid_addr (real_str, 1)) || (!valid_addr(real_stp - 1, 1)))
- { real_str = areas[A_text].first_addr;
- real_stp = areas[A_text].last_addr;
- }
- segment_str_addr = real_str;
- segment_stp_addr = real_stp;
- segment_len = (real_stp - real_str) / EVAL_SEGMENTS;
- if (segment_len <= 0)
- segment_len = 1;
-
- for (i = 0; i < EVAL_SEGMENTS; i++)
- {
- evaluation_data[i].start_addr = i * segment_len + real_str;
- evaluation_data[i].stop_addr = (i + 1) * segment_len - 1 + real_str;
- evaluation_data[i].hits_count = 0;
- }
- total_hits_count = 0;
- }
- /* ---------------------------------------------------------------------- */
-